package com.gitee.fivefaith.hikpreview.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;

/**
 * Jackson 工具类（含日志）
 *
 * <p>
 * 线程安全：ObjectMapper 是单例且只读配置，可直接并发使用。
 *
 * @author ZhaoAnchi
 * @version 1.0
 * @since 2025-08-07
 */
@Slf4j
public final class JacksonUtils {

    /**
     * 全局单例 ObjectMapper（已按常用场景预配置）
     */
    private static final ObjectMapper MAPPER = new ObjectMapper()
        // 忽略不存在字段
        .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
        // 时间用字符串输出
        .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
        // 下划线 → 驼峰（反序列化 + 序列化同时生效）
        .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
        // 注册 Java 8 时间模块
        .registerModule(new JavaTimeModule()).registerModule(new SimpleModule()
            // Long 转 String(防 JS 精度丢失)
            .addSerializer(Long.class, ToStringSerializer.instance));

    /* ---------- 单例访问 ---------- */

    public static ObjectMapper getMapper() {
        return MAPPER;
    }

    /* ---------- 序列化 ---------- */

    public static String toJson(Object obj) {
        try {
            String json = MAPPER.writeValueAsString(obj);
            log.debug("toJson >>> {}", json);
            return json;
        } catch (JsonProcessingException e) {
            log.error("序列化失败, obj={}", obj, e);
            throw new IllegalArgumentException("序列化失败", e);
        }
    }

    public static byte[] toJsonBytes(Object obj) {
        try {
            byte[] bytes = MAPPER.writeValueAsBytes(obj);
            log.debug("toJsonBytes >>> {} bytes", bytes.length);
            return bytes;
        } catch (JsonProcessingException e) {
            log.error("序列化失败, obj={}", obj, e);
            throw new IllegalArgumentException("序列化失败", e);
        }
    }

    /* ---------- 反序列化 ---------- */

    public static <T> T formatJson(String json, Class<T> clazz) {
        try {
            log.debug("fromJson <<< {}", json);
            return MAPPER.readValue(json, clazz);
        } catch (IOException e) {
            log.error("反序列化失败, json={}, clazz={}", json, clazz.getSimpleName(), e);
            throw new IllegalArgumentException("反序列化失败", e);
        }
    }

    public static <T> T formatJson(String json, TypeReference<T> typeRef) {
        try {
            log.debug("fromJson(TypeRef) <<< {}", json);
            return MAPPER.readValue(json, typeRef);
        } catch (IOException e) {
            log.error("反序列化失败, json={}, typeRef={}", json, typeRef, e);
            throw new IllegalArgumentException("反序列化失败", e);
        }
    }

    public static <T> T formatJson(InputStream in, Class<T> clazz) {
        try {
            log.debug("fromJson(InputStream) <<< {}", clazz.getSimpleName());
            return MAPPER.readValue(in, clazz);
        } catch (IOException e) {
            log.error("反序列化失败, clazz={}", clazz.getSimpleName(), e);
            throw new IllegalArgumentException("反序列化失败", e);
        }
    }

    public static <T> List<T> formatJsonList(String json, Class<T> clazz) {
        try {
            log.debug("fromJsonList <<< {}", json);
            return MAPPER.readValue(json, MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
        } catch (IOException e) {
            log.error("反序列化为 List 失败, json={}, clazz={}", json, clazz.getSimpleName(), e);
            throw new IllegalArgumentException("反序列化为 List 失败", e);
        }
    }

    public static Map<String, Object> formatJsonMap(String json) {
        return formatJson(json, new TypeReference<Map<String, Object>>() {});
    }

    /* ---------- 树模型 ---------- */

    public static JsonNode readTree(String json) {
        try {
            log.debug("readTree <<< {}", json);
            return MAPPER.readTree(json);
        } catch (IOException e) {
            log.error("readTree 失败, json={}", json, e);
            throw new IllegalArgumentException("readTree 失败", e);
        }
    }

    public static ObjectNode createObjectNode() {
        return MAPPER.createObjectNode();
    }

    public static ArrayNode createArrayNode() {
        return MAPPER.createArrayNode();
    }

    /* ---------- 私有构造 ---------- */

    private JacksonUtils() {
        throw new AssertionError("No JacksonUtils instances for you!");
    }
}